/**
 * 
 */
package br.org.bertol.mestrado.engine.optimisation.aco;

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;

import org.apache.log4j.Logger;

import br.org.bertol.mestrado.engine.fitness.Objective;
import br.org.bertol.mestrado.engine.optimisation.AbstractRepository;
import br.org.bertol.mestrado.engine.optimisation.entity.Ant;
import br.org.bertol.mestrado.engine.optimisation.moo.AbstractParetoDominace;
import br.org.bertol.mestrado.engine.optimisation.moo.ParetoMinMaxDominace;

/**
 * @author contaqualquer
 */
public class AcoRepository<T> extends AbstractRepository<Ant<T>> {

    /***/
    private final transient ArrayList<Ant<T>> repository;

    /**
     * @param repository
     */
    public AcoRepository() {
        super(new ParetoMinMaxDominace());
        this.repository = new ArrayList<Ant<T>>();
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public void addInto(final List<Ant<T>> unitList) throws Exception {

        for (final Ant<T> ant : unitList) {
            final ArrayList<Ant<T>> tmpRepository = new ArrayList<Ant<T>>(0);

            tmpRepository.clear();

            boolean dominance = true;

            // verifica se este array domina alguem, não domina niguém ou é
            // ou é dominado por alguem
            for (Ant<T> ndAnt : repository) {

                final int paretoDominante = paretoDominace.compare(ant
                        .getHeight(), ndAnt.getHeight());

                if (paretoDominante == AbstractParetoDominace.RIGHT_DOMINE) {
                    dominance = false;

                    break;
                }

                // caso domine alguma solução
                if (paretoDominante == AbstractParetoDominace.LEFT_DOMINE) {

                    tmpRepository.add(ndAnt);

                }
            }

            if (!dominance) {
                break;
            }

            Logger
                    .getLogger(getClass())
                    .debug(
                           "Unidade candidata encontrada ----------------- : "
                    + ant);

            // caso tenha ocorrido alguma dominância
            // array temporário será maior que zero
            if (!tmpRepository.isEmpty()) {

                Logger.getLogger(getClass())
                        .debug("Atualizando respositório.....");

                for (final Ant<T> dAnt : tmpRepository) {

                    Logger
                            .getLogger(getClass())
                            .debug(
                                   "Removendo unidade ---------------------------- : "
                                           + dAnt);
                }

                repository.removeAll(tmpRepository);

                Logger.getLogger(getClass()).debug("Respositório atualizado.");

            }

            repository.add((Ant<T>) ant.clone());

        }
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Ant<T>> getParetoBorder() {
        return (List<Ant<T>>) repository.clone();
    }
}
